package com.ihr360.payroll.model.dto.salary.task.period;

import com.ihr360.payroll.model.dto.salary.embeddable.RefServiceStatistics;
import com.ihr360.payroll.model.dto.salary.report.HistoryPayPeriod;
import com.ihr360.payroll.type.PeriodState;
import com.ihr360.payroll.type.ReportState;
import com.ihr360.shared.entitywithlistener.NumberIdWithTimeAndCompanyId;
import com.vladmihalcea.hibernate.type.json.JsonBinaryType;
import com.vladmihalcea.hibernate.type.json.JsonStringType;
import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.TypeDef;
import org.hibernate.annotations.TypeDefs;

import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import java.io.Serializable;
import java.util.Date;
import java.util.List;

/**
 * 账期批次
 */

/**
 * https://github.com/damienbeaufils/spring-data-jpa-encryption-example
 * https://coderwall.com/p/ppk5bg/encrypting-your-user-s-data-in-the-db
 * https://justinrodenbostel.com/2014/06/06/part-5a-additional-credential-security-spring-data-jpa-jasypt/
 * 加密方式实现方案
 */
@Entity
@TypeDefs({
        @TypeDef(name = "json", typeClass = JsonStringType.class),
        @TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
})
@DynamicUpdate
public class PayPeriodTerm extends NumberIdWithTimeAndCompanyId<Long> {
    @ManyToOne
    @JoinColumn
    private ActivePayPeriod payPeriod;

    @ManyToOne
    @JoinColumn
    private HistoryPayPeriod historyPayPeriod;

    /**
     * 计算开始日期
     */
    @Column(nullable = false, columnDefinition = "DATE")
    private Date startOn;

    /**
     * 计算结束日期
     */
    @Column(nullable = false, columnDefinition = "DATE")
    private Date endOn;


    /**
     * 考勤周期
     */
    @Column(nullable = false, columnDefinition = "DATE")
    private Date attendanceStartOn;

    @Column(nullable = false, columnDefinition = "DATE")
    private Date attendanceEndOn;

    private int workdays = 0;
    @Column(columnDefinition = "bit default 0")
    private boolean benefitsTerm = false;

    /**
     * 账期计算的序号
     */
    @Column(nullable = false, columnDefinition = "int default 1")
    private int taskExecutionSequence;

    @Column(columnDefinition = "text")
    @Type(type = "json")
    private JobExecutionIdListWrapper jobExecutionIds;
    /**
     * 批次序号,从1开始计数
     */
    private int termIndex;

    @Enumerated(EnumType.STRING)
    @Column(nullable = false, length = 40)
    private PeriodState state = PeriodState.STAFF_CHECKING;

    @Enumerated(EnumType.STRING)
    @Column(nullable = false, length = 40)
    private ReportState reportState = ReportState.UNSTARTED;

    @Enumerated(EnumType.STRING)
    @Column(nullable = false, length = 40)
    private ReportState payslipState = ReportState.UNSTARTED;

    /**
     * 引用服务的状态统计
     */
    @Embedded
    private RefServiceStatistics refServiceStatistics;

    @Column(columnDefinition = "bit default 0")
    private boolean mergeTaxTerm;

    /**
     * 多次计算合并计税时，此计算批次依赖的前置批次
     *
     * @return
     */
    @ManyToOne(fetch = FetchType.LAZY)
    private PayPeriodTerm basedOnTerm;

    /**
     * MergeSalaryReport
     */
    private Long mergeSalaryReportId;

    /**
     * MergeSalaryReport
     */
    private Long mergeSalaryReportTermSalaryId;


    public ActivePayPeriod getPayPeriod() {
        return payPeriod;
    }

    public boolean isReportCreated() {
        return reportState == ReportState.FINISHED;
    }

    public void setPayPeriod(ActivePayPeriod payPeriod) {
        this.payPeriod = payPeriod;
    }

    public HistoryPayPeriod getHistoryPayPeriod() {
        return historyPayPeriod;
    }

    public void setHistoryPayPeriod(HistoryPayPeriod historyPayPeriod) {
        this.historyPayPeriod = historyPayPeriod;
    }



    public Date getStartOn() {
        return startOn;
    }

    public void setStartOn(Date startOn) {
        this.startOn = startOn;
    }

    public Date getEndOn() {
        return endOn;
    }

    public void setEndOn(Date endOn) {
        this.endOn = endOn;
    }

    public int getWorkdays() {
        return workdays;
    }

    public void setWorkdays(int workdays) {
        this.workdays = workdays;
    }

    public boolean isBenefitsTerm() {
        return benefitsTerm;
    }

    public void setBenefitsTerm(boolean benefitsTerm) {
        this.benefitsTerm = benefitsTerm;
    }

    public boolean isMergeTaxTerm() {
        return mergeTaxTerm;
    }

    public void setMergeTaxTerm(boolean mergeTaxTerm) {
        this.mergeTaxTerm = mergeTaxTerm;
    }

    public PeriodState getState() {
        return state;
    }

    public void setState(PeriodState state) {
        this.state = state;
    }

    public ReportState getReportState() {
        return reportState;
    }

    public void setReportState(ReportState reportState) {
        this.reportState = reportState;
    }

    public ReportState getPayslipState() {
        return payslipState;
    }

    public void setPayslipState(ReportState payslipState) {
        this.payslipState = payslipState;
    }

    public int getTermIndex() {
        return termIndex;
    }

    public void setTermIndex(int termIndex) {
        this.termIndex = termIndex;
    }

    public Date getAttendanceStartOn() {
        return attendanceStartOn != null ? attendanceStartOn : startOn;
    }

    public void setAttendanceStartOn(Date attendanceStartOn) {
        this.attendanceStartOn = attendanceStartOn;
    }

    public Date getAttendanceEndOn() {
        return attendanceEndOn != null ? attendanceEndOn : endOn;
    }

    public void setAttendanceEndOn(Date attendanceEndOn) {
        this.attendanceEndOn = attendanceEndOn;
    }

    public int getTaskExecutionSequence() {
        return taskExecutionSequence;
    }

    public void setTaskExecutionSequence(int taskExecutionSequence) {
        this.taskExecutionSequence = taskExecutionSequence;
    }

    public JobExecutionIdListWrapper getJobExecutionIds() {
        return jobExecutionIds;
    }

    public void setJobExecutionIds(JobExecutionIdListWrapper jobExecutionIds) {
        this.jobExecutionIds = jobExecutionIds;
    }

    public RefServiceStatistics getRefServiceStatistics() {
        return refServiceStatistics;
    }

    public void setRefServiceStatistics(RefServiceStatistics refServiceStatistics) {
        this.refServiceStatistics = refServiceStatistics;
    }

    public PayPeriodTerm getBasedOnTerm() {
        return basedOnTerm;
    }

    public void setBasedOnTerm(PayPeriodTerm basedOnTerm) {
        this.basedOnTerm = basedOnTerm;
    }

    public Long getMergeSalaryReportId() {
        return mergeSalaryReportId;
    }

    public void setMergeSalaryReportId(Long mergeSalaryReportId) {
        this.mergeSalaryReportId = mergeSalaryReportId;
    }

    public Long getMergeSalaryReportTermSalaryId() {
        return mergeSalaryReportTermSalaryId;
    }

    public void setMergeSalaryReportTermSalaryId(Long mergeSalaryReportTermSalaryId) {
        this.mergeSalaryReportTermSalaryId = mergeSalaryReportTermSalaryId;
    }

    public static final class JobExecutionIdListWrapper implements Serializable {
        private static final long serialVersionUID = -8043906144549339386L;
        private List<Long> jobExecutionIds;

        public JobExecutionIdListWrapper() {
        }

        public JobExecutionIdListWrapper(List<Long> jobExecutionIds) {
            this.jobExecutionIds = jobExecutionIds;
        }

        public List<Long> getJobExecutionIds() {
            return jobExecutionIds;
        }

        public void setJobExecutionIds(List<Long> jobExecutionIds) {
            this.jobExecutionIds = jobExecutionIds;
        }
    }

}